package cbs.jdtag;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.ButtonGroup;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.UnsupportedLookAndFeelException;

import cbs.jdtag.actions.LoadAction;
import cbs.jdtag.actions.NewAlignmentAction;
import cbs.jdtag.actions.SaveAsAction;
import cbs.jdtag.actions.SetEncodingActionListener;
import cbs.jdtag.actions.ShowCommandHelpAction;

/**
 * 
 *
 */
public class MainApp extends JFrame {

	private static final long serialVersionUID = 9038686420125069138L;
	private static transient final Logger LOGGER = Logger.getLogger(MainApp.class.getName());
	
	private AlignmentAreaPanel2 alignmentAreaPanel = new AlignmentAreaPanel2();
	private JScrollPane alignmentScrollPane = new JScrollPane(alignmentAreaPanel,
			JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
			JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
	private JTextField cmdInputField = new JTextField();
	private JLabel statusBar = new JLabel("Ready.");
	
	public MainApp() {
		super("jdtag");
		
		cmdInputField.setEnabled(false);
		Font f = cmdInputField.getFont();
		cmdInputField.setFont(f.deriveFont(Font.BOLD, 20));
		
		// add listeners
		addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				super.windowClosing(e);
				AppContext.shutdown();
			}});
		cmdInputField.addKeyListener(new KeyAdapter() {
			
			private List<String> history = new ArrayList<String>();
			private int historyPosition = 0;
			
			@Override
			public void keyReleased(KeyEvent e) {
				
				if (e.getKeyCode() == KeyEvent.VK_ENTER) {
					LOGGER.log(Level.FINE, "Received command \"{0}\"...", cmdInputField.getText());
					history.add(cmdInputField.getText());
					historyPosition = history.size();
					UserInputParser.parse(cmdInputField.getText());
					cmdInputField.setText("");
				}
				else if (e.getKeyCode() == KeyEvent.VK_UP) {
					if (history.size() > 0) {
						historyPosition--;
						if (historyPosition < 0) {
							historyPosition = history.size() - 1;
						}
						cmdInputField.setText(history.get(historyPosition));
						statusBar.setText("Selected history entry \"" + historyPosition + "\".");
					}
					else {
						statusBar.setText("History is empty.");
					}
				}
				else if (e.getKeyCode() == KeyEvent.VK_DOWN) {
					if (history.size() > 0) {
						historyPosition++;
						if (historyPosition >= history.size()) {
							historyPosition = 0;
						}
						cmdInputField.setText(history.get(historyPosition));
						statusBar.setText("Selected history entry \"" + historyPosition + "\".");
					}
					else {
						statusBar.setText("History is empty.");
					}
				}
			}});
		
		// add menu
    	JMenu file = new JMenu("File");
    	file.add(new NewAlignmentAction());
    	try {
			file.add(new LoadAction());
		}
    	catch (Exception e) {
    		LOGGER.log(Level.SEVERE, e.getLocalizedMessage(), e);
			JOptionPane.showMessageDialog(this,
					e.getLocalizedMessage(), "Parser configuration error",
					JOptionPane.ERROR_MESSAGE);
			System.exit(ERROR);
		}
    	file.add(new SaveAsAction());
    	
//    	JMenu settings = new JMenu("Settings");
//    	JCheckBoxMenuItem showBoxesItem = new JCheckBoxMenuItem(new ShowBoxesAction());
//    	showBoxesItem.setSelected(AppContext.getDataModel().isShowBoxes());
//    	settings.add(showBoxesItem);
    	
    	JMenu encoding = new JMenu("Encoding");
    	ButtonGroup encodingGroup = new ButtonGroup();
    	SetEncodingActionListener seal = new SetEncodingActionListener();
    	
    	JCheckBoxMenuItem latinItem = new JCheckBoxMenuItem("ISO-8859-15");
    	latinItem.addActionListener(seal);
    	encoding.add(latinItem);
    	encodingGroup.add(latinItem);
    	
    	JCheckBoxMenuItem utfItem = new JCheckBoxMenuItem("UTF-8");
    	utfItem.addActionListener(seal);
    	encoding.add(utfItem);
    	encodingGroup.add(utfItem);
    	
    	if (AppContext.getDM().getEncoding().equals(latinItem.getText())) {
    		latinItem.setSelected(true);
    	}
    	else if (AppContext.getDM().getEncoding().equals(utfItem.getText())) {
    		utfItem.setSelected(true);
    	}
    	else {
        	JCheckBoxMenuItem userItem = new JCheckBoxMenuItem();
        	userItem.setText(AppContext.getDM().getEncoding());
        	userItem.addActionListener(seal);
        	encoding.add(userItem);
        	encodingGroup.add(userItem);
        	userItem.setSelected(true);
    	}
    	
    	JMenu help = new JMenu("Help");
    	help.add(new ShowCommandHelpAction());
    	
    	JMenuBar menuBar = new JMenuBar();
    	menuBar.add(file);
    	menuBar.add(encoding);
//    	menuBar.add(settings);
    	menuBar.add(help);
		setJMenuBar(menuBar);
		
		// set windows icon
		setIconImage(AppContext.getIcon());
		
		// set layout
		setLayout(new BorderLayout());		
		add(alignmentScrollPane, BorderLayout.CENTER);
		JPanel cmdInputAndStatusPanel = new JPanel(new BorderLayout());
		cmdInputAndStatusPanel.add(cmdInputField, BorderLayout.NORTH);
		cmdInputAndStatusPanel.add(statusBar, BorderLayout.SOUTH);
		add(cmdInputAndStatusPanel, BorderLayout.SOUTH);
		
		setMinimumSize(new Dimension(800, 600));
		setSize(800, 600);
		setLocationRelativeTo(null); // the better way to center on the (primary) display :-)
	}
	
	public void setCmdInputFieldEnabled(final boolean enabled) {
		cmdInputField.setEnabled(enabled);
		if (enabled) {
			cmdInputField.requestFocusInWindow();
		}
	}
	
	public void setStatusText(final String text) {
		statusBar.setText(text);
	}
	
    public static void main( String[] args ) throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException {
    	// UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		AppContext.initialize(MainApp.class.getCanonicalName());
    }
}
